package wlcs.mybatisPlus.impl;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import eoms.common.util.SpringContextUtils;
import io.swagger.annotations.ApiModelProperty;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import wlcs.mybatisPlus.dto.ModelField;
import wlcs.mybatisPlus.dto.Page;
import wlcs.mybatisPlus.dto.WhereSqlDto;
import wlcs.mybatisPlus.exc.MybatisPlusRuntimeException;
import wlcs.mybatisPlus.inter.MybatisPlusJdbc;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>自定义的Mybatis Plus 增删改查的接口实现层</p>
 *
 * <p>项目名称：辽宁移动2020年6月</p>
 *
 * <p>注释:无需编写 mapper.xml 文件，即可获得CRUD功能</p>
 *
 * <p>Copyright: Copyright Faker(c) 2023/1/17</p>
 *
 * <p>公司: Faker</p>
 *
 * <p>项目地址: https://gitee.com/anlinxi/fakerMybatisPlusUtil.git</p>
 *
 * @author 淡梦如烟
 * @version 1.0
 * @date 2023/1/17 11:26
 */
public class MybatisPlusJdbcUtil<T> implements MybatisPlusJdbc {

    /**
     * 日志对象
     */
    private final static Logger log = Logger.getLogger(MybatisPlusJdbcUtil.class);

    /**
     * concurrent包的线程安全Map，用来存放每个实例对象。
     */
    private static ConcurrentHashMap<String, MybatisPlusJdbcUtil> mybatisPlusJdbcUtilMap = new ConcurrentHashMap<String, MybatisPlusJdbcUtil>();

    /**
     * 实体对应的表名
     */
    private String tableName;

    /**
     * 主键对应的字段名
     */
    private String tableId;

    /**
     * 表字段结构
     */
    private List<ModelField> modelFieldList = new ArrayList();

    /**
     * 表字段名称列表
     */
    private List<String> columnList = new ArrayList<String>();

    /**
     * 老系统JdbcTemplate
     */
    private JdbcTemplate jdbcTemplate;

    /**
     * 利用反射机制生成实体类
     */
    private Class<T> clazz;

    /**
     * 是否是测试模式
     */
    boolean isTest = false;

    public boolean isTest() {
        return isTest;
    }

    @Override
    public void setTest(boolean test) {
        log.info("设置测试状态:" + test);
        isTest = test;
    }

    /**
     * 获取实例
     *
     * @param clazz
     * @return
     */
    public static <T> MybatisPlusJdbcUtil<T> getInstance(Class<T> clazz) {
        if (null == clazz) {
            throw new MybatisPlusRuntimeException("Class不能为空！");
        }
        if (null != mybatisPlusJdbcUtilMap.get(clazz.getName())) {
            return mybatisPlusJdbcUtilMap.get(clazz.getName());
        }
        synchronized (MybatisPlusJdbcUtil.class) {
            MybatisPlusJdbcUtil mybatisPlusJdbcUtil = new MybatisPlusJdbcUtil();

            //检查实体类是否缺少注解
            boolean isTableName = clazz.isAnnotationPresent(TableName.class);
            if (isTableName) {
                TableName tableName = (TableName) clazz.getAnnotation(TableName.class);
                if (null == tableName.value() || "".equals(tableName.value())) {
                    throw new MybatisPlusRuntimeException("实体类无TableName注解！");
                }
                mybatisPlusJdbcUtil.tableName = tableName.value();
            }
            //是否包含注解
            boolean isTableField = false;
            boolean isTableId = false;
            Field[] fields = clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                if (isTableField == false) {
                    isTableField = fields[i].isAnnotationPresent(TableField.class);
                }
                if (isTableId == false) {
                    isTableId = fields[i].isAnnotationPresent(TableId.class);
                }
                if (isTableField && isTableId) {
                    //都找到注解了 就终止
                    break;
                }
            }
            if (!isTableField) {
                throw new MybatisPlusRuntimeException("实体类无TableField注解！");
            }

            if (!isTableId) {
                log.warn("实体类无isTableId注解！");
            }

            //获取表结构
            for (int i = 0; i < fields.length; i++) {
                ModelField modelField = new ModelField();
                modelField.setModelName(fields[i].getName());
                modelField.setModelType(fields[i].getType());
                boolean annotationPresent = fields[i].isAnnotationPresent(TableField.class);
                if (annotationPresent) {
                    // 获取注解值
                    String tableField = fields[i].getAnnotation(TableField.class).value();
                    if (null != tableField && !"".equals(tableField)) {
                        modelField.setTableField(tableField);
                        mybatisPlusJdbcUtil.columnList.add(tableField.toUpperCase());
                        boolean apiMp = fields[i].isAnnotationPresent(ApiModelProperty.class);
                        if (apiMp) {
                            modelField.setApiModelProperty(fields[i].getAnnotation(ApiModelProperty.class).value());
                        } else {
                            log.debug("类" + clazz.getName() + "的字段" + fields[i].getName() + "没有注解ApiModelProperty");
                        }
                        mybatisPlusJdbcUtil.modelFieldList.add(modelField);
                    } else {
                        log.warn("属性[" + modelField.getModelName() + "]对应表字段为空！");
                    }
                } else if (fields[i].isAnnotationPresent(TableId.class)) {
                    // 获取注解值
                    mybatisPlusJdbcUtil.tableId = fields[i].getAnnotation(TableId.class).value();
                    if (null != mybatisPlusJdbcUtil.tableId && !"".equals(mybatisPlusJdbcUtil.tableId)) {
                        modelField.setTableField(mybatisPlusJdbcUtil.tableId);
                        mybatisPlusJdbcUtil.columnList.add(mybatisPlusJdbcUtil.tableId.toUpperCase());
                        boolean apiMp = fields[i].isAnnotationPresent(ApiModelProperty.class);
                        if (apiMp) {
                            modelField.setApiModelProperty(fields[i].getAnnotation(ApiModelProperty.class).value());
                        } else {
                            log.debug("类" + clazz.getName() + "的字段" + fields[i].getName() + "没有注解ApiModelProperty");
                        }
                        mybatisPlusJdbcUtil.modelFieldList.add(modelField);
                    } else {
                        log.warn("属性[" + modelField.getModelName() + "]对应表字段为空！");
                    }
                }
            }
            mybatisPlusJdbcUtil.clazz = clazz;
            log.debug("类[" + clazz.getName() + "]的表名为[" + mybatisPlusJdbcUtil.getTableName() + "];字段信息为:" + mybatisPlusJdbcUtil.getModelFieldList());
            mybatisPlusJdbcUtilMap.put(clazz.getName(), mybatisPlusJdbcUtil);
            return mybatisPlusJdbcUtil;
        }
    }

    /**
     * 私有化构造函数，使用getInstance()去获取实例
     */
    private MybatisPlusJdbcUtil() {
    }

    public String getTableName() {
        return tableName;
    }

    public List<ModelField> getModelFieldList() {
        return modelFieldList;
    }

    /**
     * 插入一条记录（选择字段，策略插入）
     *
     * @param entity 实体对象
     * @return
     */
    @Override
    public boolean save(Object entity) {
        Class clazz = entity.getClass();
        //sql
        StringBuffer sql = new StringBuffer();
        StringBuffer row1 = new StringBuffer();
        StringBuffer row2 = new StringBuffer();

        //参数
        List<Object> params = new ArrayList<Object>();

        sql.append("INSERT INTO ").append(this.tableName).append("(");
        //获取所有类型的字段
        for (int i = 0; i < this.modelFieldList.size(); i++) {
            ModelField modelField = this.modelFieldList.get(i);
            Field field = null;
            Object object = null;
            try {
                field = clazz.getDeclaredField(modelField.getModelName());
                field.setAccessible(true);
                object = field.get(entity);
                if (null != object) {
                    row1.append(modelField.getTableField()).append(",");
                    row2.append("?").append(",");
                    params.add(object);
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        //去掉最后的逗号
        if (row1.length() > 1) {
            row1.setLength(row1.length() - 1);
        }
        if (row2.length() > 1) {
            row2.setLength(row2.length() - 1);
        }
        sql.append(row1).append(") VALUES(").append(row2).append(")");

        int i = this.update(sql.toString(), params.toArray());
        if (i >= 1) {
            return true;
        }
        return false;
    }

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     * @return
     */
    @Override
    public boolean removeById(Serializable id) {
        if (this.tableId == null) {
            throw new MybatisPlusRuntimeException("实体类无TableId注解,无法根据主键id进行删除！");
        }
        if (id == null) {
            throw new MybatisPlusRuntimeException("removeById方法实体类主键id[" + this.tableId + "]的值不能为空！");
        }
        StringBuffer sql = new StringBuffer();
        sql.append("DELETE FROM ").append(this.tableName).append(" WHERE ").append(this.tableId).append(" = ?");
        //参数
        List<Object> params = new ArrayList<Object>();
        params.add(id);
        int i = this.update(sql.toString(), params.toArray());
        if (i >= 1) {
            return true;
        }
        return false;
    }

    /**
     * 根据 ID 选择修改
     *
     * @param entity 实体对象
     * @return
     */
    @Override
    public boolean updateById(Object entity) {
        if (this.tableId == null) {
            throw new MybatisPlusRuntimeException("实体类无TableId注解,无法根据主键id进行修改！");
        }
        Class clazz = entity.getClass();
        //sql
        StringBuffer sql = new StringBuffer();
        StringBuffer row1 = new StringBuffer();

        //参数
        List<Object> params = new ArrayList<Object>();

        sql.append("UPDATE  ").append(this.tableName).append(" SET ");
        Object idValue = null;
        //获取所有类型的字段
        for (int i = 0; i < this.modelFieldList.size(); i++) {
            ModelField modelField = this.modelFieldList.get(i);
            Field field = null;
            Object object = null;
            try {
                field = clazz.getDeclaredField(modelField.getModelName());
                field.setAccessible(true);
                object = field.get(entity);
                if (this.tableId.equals(modelField.getTableField())) {
                    //主键id
                    if (null != object && !"".equals(object)) {
                        idValue = object;
                    } else {
                        throw new MybatisPlusRuntimeException("updateById方法实体类主键id[" + modelField.getTableField() + "][" + modelField.getModelName() + "]的值不能为空！");
                    }
                } else {
                    if (null != object) {
                        row1.append(modelField.getTableField()).append(" = ?").append(",");
                        params.add(object);
                    }

                }

            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        //去掉最后的逗号
        if (row1.length() > 1) {
            row1.setLength(row1.length() - 1);
        } else {
            return false;
        }

        sql.append(row1).append(" WHERE ").append(this.tableId).append(" = ?");
        params.add(idValue);
        int i = this.update(sql.toString(), params.toArray());
        if (i >= 1) {
            return true;
        }
        return false;
    }

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     * @return
     */
    @Override
    public T getById(Serializable id) {
        if (this.tableId == null) {
            if (this.clazz != null) {
                throw new MybatisPlusRuntimeException("实体类(" + this.clazz.getName() + ")无TableId注解,无法根据主键id进行查询！");
            } else {
                throw new MybatisPlusRuntimeException("实体类无clazz和TableId注解,无法根据主键id进行查询！");
            }
        }
        //sql
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT ").append(this.getSelectSql()).append(" FROM ").append(this.tableName).append(" WHERE 1 = 1 ").append(" AND ").append(this.tableId).append(" = ?");
        //参数
        List<Object> params = new ArrayList<Object>();
        params.add(id);
        //查询
        List objectList = this.queryForList(sql.toString(), params.toArray());
        if (null == objectList || objectList.size() <= 0) {
            return null;
        }
        //转换
        List<T> tList = listMapToListBean(objectList);
        return tList.get(0);
    }

    /**
     * 翻页查询
     *
     * @param page      翻页对象
     * @param columnMap 表字段 map 对象
     * @return
     */
    @Override
    public Page page(Page page, Map columnMap) {

        //sql
        StringBuffer sql1 = new StringBuffer();

        //封装的查询参数信息
        WhereSqlDto whereSqlDto = getWhereSql(columnMap);

        //参数
        List<Object> params = whereSqlDto.getParams();

        //查询行数
        StringBuffer count1 = new StringBuffer();
        count1.append("SELECT COUNT(1) FROM ").append(this.tableName).append(" WHERE 1 = 1 ").append(whereSqlDto.getSql());
        long total = this.queryForInt(count1.toString(), params.toArray());
        page.setTotal(total);

        sql1.append("SELECT ").append(this.getSelectSql()).append(" FROM ").append(this.tableName).append(" WHERE 1 = 1 ").append(whereSqlDto.getSql());

        StringBuffer selectPage = new StringBuffer();

        //分页查询
        selectPage.append("SELECT PAGEOUT.* FROM ( " +
                "SELECT PAGEIN.*, ROWNUM AS XXXXX_ROWNUM from ( ");

        selectPage.append(sql1);

        selectPage.append(" )PAGEIN  " +
                " )PAGEOUT WHERE (PAGEOUT.XXXXX_ROWNUM > " + page.getStartRow() + " and PAGEOUT.XXXXX_ROWNUM <= " + page.getEndRow() + ") OR (" + page.getStartRow() + " = 0 and " + page.getEndRow() + " = 0)");
        //查询
        List objectList = this.queryForList(selectPage.toString(), params.toArray());

        //转换
        List<T> tList = listMapToListBean(objectList);
        page.setRecords(tList);

        return page;
    }

    /**
     * 查询（根据 columnMap 条件）
     *
     * @param columnMap 表字段 map 对象
     * @return
     */
    @Override
    public List<T> listByMap(Map columnMap) {
        //sql
        StringBuffer sql = new StringBuffer();

        WhereSqlDto whereSqlDto = getWhereSql(columnMap);
        //参数
        List<Object> params = whereSqlDto.getParams();

        sql.append("SELECT ").append(this.getSelectSql()).append(" FROM ").append(this.tableName).append(" WHERE 1 = 1 ").append(whereSqlDto.getSql());
        //查询
        List objectList = this.queryForList(sql.toString(), params.toArray());

        //转换
        List<T> tList = listMapToListBean(objectList);

        return tList;
    }

    /**
     * 获取select的sql
     *
     * @return
     */
    private StringBuffer getSelectSql() {
        StringBuffer sql = new StringBuffer();
        //查询表头数据分解
        for (int i = 0; i < this.modelFieldList.size(); i++) {
            ModelField modelField = this.modelFieldList.get(i);
            sql.append(modelField.getTableField().toUpperCase()).append(",");
        }
        if (sql.length() > 0) {
            sql.setLength(sql.length() - 1);
        }
        return sql;
    }

    /**
     * 根据 idList 查询列表
     *
     * @param idList 主键ID列表
     * @return
     */
    @Override
    public List<T> listByIds(Collection idList) {
        if (idList == null || idList.isEmpty()) {
            throw new MybatisPlusRuntimeException("查询列表的id集合不能为空！");
        }
        //sql
        StringBuffer sql = new StringBuffer();

        //参数
        StringBuilder inSql = new StringBuilder();
        Iterator<Object> objectIterator = idList.iterator();
        while (objectIterator.hasNext()) {
            inSql.append("'").append(objectIterator.next()).append("',");
        }
        if (inSql.length() > 0) {
            inSql.setLength(inSql.length() - 1);
        }

        sql.append("SELECT ").append(this.getSelectSql()).append(" FROM ").append(this.tableName).append(" WHERE 1 = 1 ").append(this.tableId).append(" IN (").append(inSql).append(")");
        //查询
        List objectList = this.queryForList(sql.toString(), new Object[]{});

        //转换
        List<T> tList = listMapToListBean(objectList);

        return tList;
    }

    /**
     * 获取jdbc
     *
     * @return
     */
    private JdbcTemplate getJdbcTemplate() {
        //todo 各系统自己实现
        if (jdbcTemplate == null) {
            jdbcTemplate = (JdbcTemplate) SpringContextUtils.getBean("JdbcTemplate");
        }
        return jdbcTemplate;

    }

    /**
     * 更新的方法
     *
     * @param sql    预编译sql
     * @param params 参数
     * @return
     */
    private int update(String sql, Object[] params) {
        if (isTest) {
            log.info(this.printSqlLog(sql.toString(), params));
            return 1;
        } else {
            log.info(this.printSqlLog(sql.toString(), params));
        }
        return getJdbcTemplate().update(sql, params);
    }

    /**
     * 查询的方法
     *
     * @param sql    预编译sql
     * @param params 参数
     * @return
     */
    private List queryForList(String sql, Object[] params) {
        if (isTest) {
            log.info(this.printSqlLog(sql.toString(), params));
            String endSql = " FROM " + this.tableName + " WHERE 1 = 1";
            String select = sql.substring("SELECT ".length(), sql.lastIndexOf(endSql));
            String[] selectArgs = select.split(",");
            List<Map> list = new ArrayList();
            for (int i = 0; i < 2; i++) {
                Map<String, Object> map = new HashMap<String, Object>();
                for (String arg : selectArgs) {
                    map.put(arg, arg + "_" + (i + 1));
                }
                list.add(map);
            }

            return list;
        } else {
            log.info(this.printSqlLog(sql.toString(), params));
        }
        return getJdbcTemplate().queryForList(sql, params);
    }

    /**
     * 查询行数
     *
     * @param sql
     * @param params
     * @return
     */
    private long queryForInt(String sql, Object[] params) {
        if (isTest) {
            log.info(this.printSqlLog(sql.toString(), params));
            return 1;
        } else {
            log.info(this.printSqlLog(sql.toString(), params));
        }
        return getJdbcTemplate().queryForLong(sql, params);
    }

    /**
     * 打印日志
     *
     * @param sql
     * @param params
     * @return
     */
    private String printSqlLog(String sql, Object[] params) {
        StringBuffer stringBuffer = new StringBuffer();
        String endSql = sql;
        stringBuffer.append("预编译SQL[").append(sql).append("],参数[");
        for (Object object : params) {
            stringBuffer.append(String.valueOf(object)).append(",");
            try {
                if (object != null && object instanceof Date) {
                    Date date = (Date) object;
                    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    endSql = endSql.replaceFirst("\\?", " '" + sdf1.format(date) + "' ");
                } else {
                    endSql = endSql.replaceFirst("\\?", " '" + String.valueOf(object) + "' ");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //去掉最后一个逗号
        stringBuffer.setLength(stringBuffer.length() - 1);
        stringBuffer.append("],\n编译后SQL[").append(endSql).append("]");
        return stringBuffer.toString();
    }

    /**
     * 封装的查询参数信息
     *
     * @param columnMap
     * @return
     */
    private WhereSqlDto getWhereSql(Map columnMap) {
        WhereSqlDto whereSql = new WhereSqlDto();

        //查询条件参数分解
        Iterator<Map.Entry<String, Object>> entries = columnMap.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<String, Object> entry = entries.next();
            String oriKey = entry.getKey();
            //todo 时间类型的非eq查询可能有问题
            Object orivValue = entry.getValue();
            if (null != orivValue) {
                //是包含的字段，才进行处理
                //模糊查询
                if (oriKey.toLowerCase().startsWith("like:")) {
                    String key = oriKey.substring("like:".length(), oriKey.length()).toUpperCase();
                    if (this.columnList.contains(key)) {
                        whereSql.getSql().append(" AND ").append(key).append(" LIKE '%").append(orivValue).append("%' ");
                    }
                } else if (oriKey.toLowerCase().startsWith("lt:")) {
                    //小于
                    String key = oriKey.substring("lt:".length(), oriKey.length()).toUpperCase();
                    if (this.columnList.contains(key)) {
                        whereSql.getSql().append(" AND ").append(key).append(" < ? ");
                        whereSql.getParams().add(orivValue);
                    }
                } else if (oriKey.toLowerCase().startsWith("gt:")) {
                    //大于
                    String key = oriKey.substring("gt:".length(), oriKey.length()).toUpperCase();
                    if (this.columnList.contains(key)) {
                        whereSql.getSql().append(" AND ").append(key).append(" > ? ");
                        whereSql.getParams().add(orivValue);
                    }
                } else if (oriKey.startsWith("likeLeft:")) {
                    //左like
                    String key = oriKey.substring("likeLeft:".length(), oriKey.length()).toUpperCase();
                    if (this.columnList.contains(key)) {
                        whereSql.getSql().append(" AND ").append(key).append(" LIKE '%").append(orivValue).append("' ");
                    }
                } else if (oriKey.startsWith("likeRight:")) {
                    //右like
                    String key = oriKey.substring("likeRight:".length(), oriKey.length()).toUpperCase();
                    if (this.columnList.contains(key)) {
                        whereSql.getSql().append(" AND ").append(key).append(" LIKE '").append(orivValue).append("%' ");
                    }
                } else {
                    //eq等于条件查询
                    String key = oriKey.toUpperCase();
                    if (this.columnList.contains(key)) {
                        whereSql.getSql().append(" AND ").append(key).append(" = ? ");
                        whereSql.getParams().add(orivValue);
                    }
                }
            }
        }
        return whereSql;
    }

    /**
     * 查询出的原始Map列表转T列表
     *
     * @param objectList
     * @return
     */
    private List<T> listMapToListBean(List objectList) {
        List<T> tList = new ArrayList();
        //列表转
        for (Object object : objectList) {
            if (null != object && object instanceof Map) {
                Map objectMap = (Map) object;
                try {
                    T t = this.clazz.newInstance();
                    for (int i = 0; i < this.modelFieldList.size(); i++) {
                        ModelField modelField = this.modelFieldList.get(i);
                        Object object2 = objectMap.get(modelField.getTableField().toUpperCase());
                        try {
                            if (null != object2) {
                                Field field = this.clazz.getDeclaredField(modelField.getModelName());
                                field.setAccessible(true);
                                if (modelField.getModelType().equals(String.class)) {
                                    field.set(t, object2);
                                } else if (modelField.getModelType().equals(Integer.class) || modelField.getModelType().equals(int.class)) {
                                    field.set(t, Integer.parseInt(String.valueOf(object2)));
                                } else if (modelField.getModelType().equals(Long.class) || modelField.getModelType().equals(long.class)) {
                                    if (object2 instanceof BigDecimal) {
                                        BigDecimal bigDecimal = (BigDecimal) object2;
                                        field.set(t, bigDecimal.longValue());
                                    } else {
                                        field.set(t, Long.parseLong(String.valueOf(object2)));
                                    }
                                } else if (modelField.getModelType().equals(BigDecimal.class)) {
                                    field.set(t, object2);
                                } else if (modelField.getModelType().equals(Date.class)) {
                                    field.set(t, object2);
                                }

                            }

                        } catch (Exception e) {
                            log.warn("对象[" + clazz.getName() + "]属性[" + modelField.getModelName() + "][" + modelField.getModelType() + "]写入表字段[" + modelField.getTableField() + "]的值[" + object2 + "]异常:" + e.getMessage());
                            e.printStackTrace();
                        }
                    }
                    tList.add(t);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return tList;
    }

    /**
     * 查询列表
     *
     * @param queryWrapper 实体对象封装操作类
     * @return
     */
    @Override
    public List<T> list(QueryWrapper queryWrapper) {
        //封装的查询参数信息
        WhereSqlDto whereSqlDto = getQueryWrapperSql(queryWrapper);
        //sql
        StringBuffer sql = whereSqlDto.getSql();
        //参数
        List<Object> params = whereSqlDto.getParams();
        //查询
        List objectList = this.queryForList(sql.toString(), params.toArray());

        //转换
        List<T> tList = listMapToListBean(objectList);

        return tList;
    }

    /**
     * 过滤mybatis参数
     */
    private final Pattern pattern = Pattern.compile("\\#\\{([^}]*)\\}");

    /**
     * 解析Wrapper生成sql
     *
     * @param queryWrapper
     * @return
     */
    private WhereSqlDto getQueryWrapperSql(QueryWrapper queryWrapper) {
        WhereSqlDto whereSql = new WhereSqlDto();
        StringBuffer sql = new StringBuffer();
        if (null != queryWrapper.getSqlFirst() && !"".equals(queryWrapper.getSqlFirst())) {
            sql.append(queryWrapper.getSqlFirst()).append(" ");
        }

        if (null != queryWrapper.getSqlSelect() && !"".equals(queryWrapper.getSqlSelect())) {
            sql.append("SELECT ").append(queryWrapper.getSqlSelect()).append(" FROM ").append(this.tableName).append(" WHERE 1 = 1 ");
        } else {
            sql.append("SELECT ").append(this.getSelectSql()).append(" FROM ").append(this.tableName).append(" WHERE 1 = 1 ");
        }

        if (null != queryWrapper.getSqlSegment() && !"".equals(queryWrapper.getSqlSegment()) && null != queryWrapper.getParamNameValuePairs() && !queryWrapper.getParamNameValuePairs().isEmpty()) {
            String where = queryWrapper.getSqlSegment();


            Matcher matcher = pattern.matcher(where);
            while (matcher.find()) {
                String replaceKey = matcher.group();
//                log.info(replaceKey);
                String key = replaceKey.substring("#{ew.paramNameValuePairs.".length(), replaceKey.length() - 1);
//                log.info(key);
                Object value = queryWrapper.getParamNameValuePairs().get(key);
                if (null != value) {
                    where = where.replace(replaceKey, "?");
                    whereSql.getParams().add(value);
                }
            }

//            long seq = queryWrapper.getParamNameSeq().longValue();
//            for (int i = 0; i <= seq; i++) {
//                String key = "MPGENVAL" + i;
//                String replaceKey = "#{ew.paramNameValuePairs." + key + "}";
//                Object value = queryWrapper.getParamNameValuePairs().get(key);
//                if (null != value) {
//                    where = where.replace(replaceKey, "?");
//                    whereSql.getParams().add(value);
//                }
//            }
            sql.append(" AND ").append(where);
        }


        whereSql.setSql(sql);
        return whereSql;
    }

    /**
     * 翻页查询
     *
     * @param page         翻页对象
     * @param queryWrapper 实体对象封装操作类 {@link QueryWrapper}
     */
    @Override
    public Page page(Page page, QueryWrapper queryWrapper) {
        //sql
        StringBuffer sql1 = new StringBuffer();

        //封装的查询参数信息
        WhereSqlDto whereSqlDto = getQueryWrapperSql(queryWrapper);

        //参数
        List<Object> params = whereSqlDto.getParams();

        //查询行数
        StringBuffer count1 = new StringBuffer();
        count1.append("SELECT COUNT(1) FROM ( ").append(whereSqlDto.getSql()).append(" )");
        long total = this.queryForInt(count1.toString(), params.toArray());
        page.setTotal(total);

        sql1.append(whereSqlDto.getSql());

        StringBuffer selectPage = new StringBuffer();

        //分页查询
        selectPage.append("SELECT PAGEOUT.* FROM ( " +
                "SELECT PAGEIN.*, ROWNUM AS XXXXX_ROWNUM from ( ");

        selectPage.append(sql1);

        selectPage.append(" )PAGEIN  " +
                " )PAGEOUT WHERE (PAGEOUT.XXXXX_ROWNUM > " + page.getStartRow() + " and PAGEOUT.XXXXX_ROWNUM <= " + page.getEndRow() + ") OR (" + page.getStartRow() + " = 0 and " + page.getEndRow() + " = 0)");
        //查询
        List objectList = this.queryForList(selectPage.toString(), params.toArray());

        //转换
        List<T> tList = listMapToListBean(objectList);
        page.setRecords(tList);

        return page;
    }

    /**
     * 初始化时手动设置JdbcTemplate
     *
     * @param jdbcTemplate
     */
    @Override
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    /**
     * 查询一条数据
     *
     * @param queryWrapper
     * @return
     */
    @Override
    public T getOne(QueryWrapper queryWrapper) {
        List<T> list = this.list(queryWrapper);
        if (list == null || list.size() <= 0) {
            return null;
        }
        return list.get(0);
    }
}
